﻿#pragma once
#include "as_socket.h"
#include "as_address.h"
#include "as_callback.h"
#include "as_promise.h"
#include "as_awaiter.h"
#include <memory>
#include <set>

namespace as
{
	namespace net
	{
		class Acceptor;
		class EpollWatch;
		class TcpServer
		{
		public:
			TcpServer(std::shared_ptr<EpollWatch> &ep, const Address &listenAddr, 
				const std::string_view &name);
			TcpServer(std::shared_ptr<EpollWatch> &ep, const char *addr, int port, 
				const std::string_view &name) : TcpServer(ep, Address(addr, port), name) {}
			virtual ~TcpServer();

			void Start();
			void Stop();

			bool IsStop() { return is_stop_; }

		public:
			int GetConnCount();
			TcpConnectionPtr GetConn(int connId);

			const char *GetName();

			as::co::Awaitable<as::co::as_promise> HandleCoRead(TcpConnectionPtr conn);
			void HandleNewConn(socket_fd fd, Address &peek);
			void HandleCloseConn(const TcpConnectionPtr &conn);
			virtual void HandleMsg(TcpConnectionPtr &conn, ByteBufferPtr &buf, int size);

			void SendMsg(int connId, ByteBufferPtr &buf);
			void SendMsg(int connId, ByteBuffer &buf);
			void SendMsg(int connId, const char *buf, int size);

		protected:
			void SendMsgByConn(TcpConnectionPtr &conn, const char *buf, int size);

		public:
			void SetConnCb(ConnChangeCb fun);
			void SetMsgCb(MsgCallback fun);
			void SetCloseCb(CloseCallback fun);

		private:
			std::weak_ptr<EpollWatch> epoll_watch_;
			std::unique_ptr<Acceptor> acceptor_;
			std::string svr_name_;

			//all conn obj
			std::unordered_map<int, TcpConnectionPtr> conns_;

			ConnChangeCb conn_change_cb_;
			MsgCallback msg_cb_;
			CloseCallback close_cb_;
			bool is_stop_ = false;
		};
	}
}
